package com.lemon.components.ant.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import com.lemon.components.ant.beans.ProjectInfo;
import com.lemon.components.ant.project.beans.CodeMakerInfo;
import com.lemon.components.ant.project.beans.ColumnInfo;
import com.lemon.components.ant.project.beans.ControllerInfo;
import com.lemon.components.ant.project.beans.MethodInfo;
import com.lemon.components.ant.project.beans.ModelInfo;
import com.lemon.components.ant.project.beans.ServiceInfo;
import com.lemon.components.docs.mysql.MysqlLocalTool;
import com.lemon.ui.codemaker.component.RecentlyFile;
import com.system.core.security.NameUtil;

public class ConfigUtil {
	
	private static ConfigUtil configUtil = null;
	
	private static Properties properties = new Properties();
	private static ProjectInfo projectInfo = null;
	private static ServiceInfo serviceInfo = null;
	private static MethodInfo methodInfo = null;
	private static ModelInfo beanInfo = null;
	private static Pattern pattern = Pattern.compile("serviceInfo\\.method\\.param\\.(.*)");
	private static String configPath;
	
	private ConfigUtil(String configPath) {
		try {
			if(configPath != null) {
				FileInputStream configFile = new FileInputStream(configPath);
				properties.load(new InputStreamReader(configFile, "utf-8"));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	private ConfigUtil() {}
	
	public static ConfigUtil getInstance(String configPath) {
		return configUtil = new ConfigUtil(configPath);
	}
	
	public void reloadProperties() {
		properties.clear();
		try {
			properties.load(new InputStreamReader(new FileInputStream(getConfigPath()), "utf-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void loadPropertiesFrom(String filePath) throws IOException {
		File file = new File(filePath);
		if(!file.exists())
			throw new FileNotFoundException();
		properties.load(new FileInputStream(filePath));
		FileUtil.copyFile(filePath, ConfigUtil.class.getResource("/code/maven-project-template/codemaker.properties").getFile());
		setConfigPath(filePath);
	}
	
	public Properties getProperties() {
		return properties;
	}
	
	public void saveAsFile(String saveAsFilePath) {
		try {
			properties.store(new FileOutputStream(saveAsFilePath), "created by codemaker");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	public ControllerInfo getControllerInfo() {
		ControllerInfo controllerInfo = new ControllerInfo();
		controllerInfo.setServiceInfo(getServiceInfo());
		controllerInfo.setUrlPrefix(properties.getProperty("controller.url.prefix"));
		controllerInfo.setBaseUrl(NameUtil.javaName2_(serviceInfo.getServiceName()));
		controllerInfo.setParentMenuId(Long.parseLong(properties.getProperty("controller.parentMenuId","1")));
		controllerInfo.setParentResourceId(Long.parseLong(properties.getProperty("controller.parentResourceId","1")));
		controllerInfo.setModelname(properties.getProperty("controller.modelname"));
		String modelName = properties.getProperty("serviceInfo.modelName");
		controllerInfo.setTableInfo(MysqlLocalTool.getTableInfo(projectInfo, NameUtil.javaName2_(modelName)));
		return controllerInfo;
	}
	
	public CodeMakerInfo getCodeMakerInfo() {
		CodeMakerInfo codeMakerInfo = new CodeMakerInfo();
		reloadProperties();
		String initdb = properties.getProperty("codemaker.initdb");
		codeMakerInfo.setInitdb(Boolean.parseBoolean(initdb));
		return codeMakerInfo;
	}
	
	public ProjectInfo getProjectInfoNoTable() {
		ProjectInfo projectInfo2 = new ProjectInfo();
		projectInfo2.setProjectPath(properties.getProperty("projectinfo.projectPath"));
		projectInfo2.setArtifactId(properties.getProperty("projectinfo.artifactId"));
		projectInfo2.setCompanyName(properties.getProperty("projectinfo.companyName"));
		projectInfo2.setDescription(properties.getProperty("projectinfo.description"));
		projectInfo2.setDbhost(properties.getProperty("projectinfo.dbhost"));
		projectInfo2.setDbname(properties.getProperty("projectinfo.dbname"));
		projectInfo2.setDbusername(properties.getProperty("projectinfo.dbusername"));
		projectInfo2.setDbpasswd(properties.getProperty("projectinfo.dbpasswd"));
		projectInfo2.setServerPort(properties.getProperty("projectinfo.serverport"));
		return projectInfo2;
	}
	
	public ProjectInfo getProjectInfo() {
		projectInfo = new ProjectInfo();
		projectInfo.setProjectPath(properties.getProperty("projectinfo.projectPath"));
		projectInfo.setArtifactId(properties.getProperty("projectinfo.artifactId"));
		projectInfo.setCompanyName(properties.getProperty("projectinfo.companyName"));
		projectInfo.setDescription(properties.getProperty("projectinfo.description"));
		projectInfo.setDbhost(properties.getProperty("projectinfo.dbhost"));
		projectInfo.setDbname(properties.getProperty("projectinfo.dbname"));
		projectInfo.setDbusername(properties.getProperty("projectinfo.dbusername"));
		projectInfo.setDbpasswd(properties.getProperty("projectinfo.dbpasswd"));
		projectInfo.setServerPort(properties.getProperty("projectinfo.serverport"));
		projectInfo.setTables(MysqlLocalTool.getTableInfo(projectInfo));
		return projectInfo;
	}
	
	public ServiceInfo getServiceInfo() {
		serviceInfo = new ServiceInfo();
		String modelName = properties.getProperty("serviceInfo.modelName");
		serviceInfo.setModelName(modelName);
		String serviceName = properties.getProperty("serviceInfo.serviceName");
		serviceInfo.setServiceName(StringUtils.isBlank(serviceName)?modelName:serviceName);
		serviceInfo.setProjectInfo(getProjectInfo());
		serviceInfo.setTableInfo(MysqlLocalTool.getTableInfo(projectInfo, NameUtil.javaName2_(modelName)));
		serviceInfo.setColumns(MysqlLocalTool.getColumnInfo(projectInfo, NameUtil.javaName2_(modelName)));
		
		for(ColumnInfo column:  serviceInfo.getColumns()) {
			if(column.isPrikey()) {
				serviceInfo.setKeyColumn(column);
				break;
			}
		}
		
		return serviceInfo;
	}
	
	public MethodInfo getMethodInfo() {
		methodInfo = new MethodInfo();
		methodInfo.setServiceInfo(getServiceInfo());
		methodInfo.setServiceName(getServiceInfo().getServiceName());
		methodInfo.setMethodName(properties.getProperty("serviceInfo.methodName"));
		
		Map<String, String[]> params = new HashMap<String, String[]>();

		properties.keySet().forEach(param -> {
			if(param.toString().startsWith("serviceInfo.method.param")) {
				Matcher m = pattern.matcher(param.toString());
				String[] paramTmp = properties.getProperty(param.toString()).split(",");
				if (m.find()) {
				    params.put(m.group(1), paramTmp);
				}
			}
		});
		methodInfo.setParams(params);
		
		return methodInfo;
	}

	public String getConfigPath() throws Exception {
		if(StringUtils.isBlank(configPath)) {
			configPath = RecentlyFile.getLastConfigFilePath();
		}
		return configPath;
	}
	
	public void setConfigPath(String configPath) {
		ConfigUtil.configPath = configPath;
	}
}
